package com.gitee.cirnochat.common.utils;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTValidator;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.gitee.cirnochat.common.exception.BusinessException;
import com.gitee.cirnochat.common.model.enums.ErrorCode;
import org.springframework.stereotype.Component;

import java.security.KeyPair;
import java.time.Duration;
import java.util.Map;

@Component
public final class JwtTool {
    private final JWTSigner jwtSigner;

    public JwtTool(KeyPair keyPair) {
        this.jwtSigner = JWTSignerUtil.createSigner("rs256", keyPair);
    }

    /**
     * 创建 access-token
     *
     * @param userId 用户ID
     * @return access-token
     */
    public String createAccessToken(Long userId, Duration ttl) {
        return JWT.create()
                .setPayload("user", userId)
                .setPayload("type", "access") // 额外标明 token 类型
                .setExpiresAt(new DateTime(System.currentTimeMillis() + ttl.toMillis()))
                .setSigner(jwtSigner)
                .sign();
    }

    /**
     * 创建 refresh-token
     *
     * @param userId 用户ID
     * @return refresh-token
     */
    public String createRefreshToken(Long userId, Duration ttl) {
        return JWT.create()
                .setPayload("user", userId)
                .setPayload("type", "refresh") // 额外标明 token 类型
                .setExpiresAt(new DateTime(System.currentTimeMillis() + ttl.toMillis()))
                .setSigner(jwtSigner)
                .sign();
    }

    /**
     * 解析 JWT token 并返回 payload 数据
     *
     * @param token JWT 字符串
     * @return 解析得到的 payload 数据（包含 userId、type 等字段）
     */
    public Map<String, Object> parseToken(String token) {
        if (token == null) {
            throw new BusinessException(ErrorCode.NOT_TOKEN_ERROR, "Token 为空");
        }

        JWT jwt;
        try {
            jwt = JWT.of(token).setSigner(jwtSigner);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无效的 token：" + e.getMessage());
        }

        if (!jwt.verify()) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "token 签名验证失败");
        }

        try {
            JWTValidator.of(jwt).validateDate();
        } catch (ValidateException e) {
            throw new BusinessException(ErrorCode.TOKEN_EXPIRED, "accessToken 失效，可刷新");
        }

        Map<String, Object> payload = jwt.getPayloads();
        if (!payload.containsKey("user") || !payload.containsKey("type")) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "token 信息不完整");
        }

        return payload;
    }

    /**
     * 忽略过期时间去解析 JWT token 并返回 userId
     *
     * @param token JWT 字符串
     * @return 解析得到的 userId 或 null
     */
    public Long ignoreParseTokenToUserId(String token) {
        JWT jwt;
        try {
            jwt = JWT.of(token).setSigner(jwtSigner);
            if (!jwt.verify()) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "token 签名验证失败");
            }
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无效的 token：" + e.getMessage());
        }
        Map<String, Object> payload = jwt.getPayloads();
        if (!payload.containsKey("user") || !payload.containsKey("type")) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "token 信息不完整");
        }

       return Long.parseLong(String.valueOf(payload.get("user")));
    }

    /**
     * 解析 JWT token 并返回 payload 数据 - UserId
     *
     * @param token JWT 字符串
     * @return 解析得到的 payload 数据（包含 userId、type 等字段）
     */
    public Long parseTokenToUserId(String token) {
        if (token == null) {
            throw new BusinessException(ErrorCode.NOT_TOKEN_ERROR, "Token 为空");
        }

        JWT jwt;
        try {
            jwt = JWT.of(token).setSigner(jwtSigner);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无效的 token");
        }

        if (!jwt.verify()) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "token 签名验证失败");
        }

        try {
            JWTValidator.of(jwt).validateDate();
        } catch (ValidateException e) {
            throw new BusinessException(ErrorCode.TOKEN_EXPIRED, "accessToken 失效，可刷新");
        }

        Map<String, Object> payload = jwt.getPayloads();
        if (!payload.containsKey("user") || !payload.containsKey("type")) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "token 信息不完整");
        }

        return Long.parseLong(String.valueOf(payload.get("user")));
    }

}